
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <cerrno>
#include <sys/select.h>
#include <string.h>

int SetNoBlock(int fd)
{
    int ret = fcntl(fd, F_GETFL);  // 获取原来fd的读写标志位，就比如：open时设置的O_RDONLY，O_RDWR等等
    if (ret == -1)
        return -1;
    fcntl(fd, F_SETFL, ret | O_NONBLOCK);
    // fcntl 更换为设置读写标准位，并在原来标准位的基础上添加 非阻塞模式
    return 0;
}



int main()
{
    SetNoBlock(0);  //文件描述符也只需要设置一次，如果还要设置标准位可以后面自己添加
    char buff[1024];
    while (1)
    {
        sleep(1);
        errno = 0;
        int ret = read(0, buff, sizeof buff - 1);
        if ( ret > 0)
        {
            buff[ret] = 0;
            std::cout << "echo# " << buff;
            continue;
        }else  if( ret == 0)
        {
            std::cout << "echo# try again"  << std::endl;
        }else if (ret == -1)
        {
            std::cout << "echo# "<< errno << ": "<< strerror(errno);
            // 由于文件描述符采用非阻塞式后，我们无法区分是错误导致，还是单纯是IO资源未就绪
        }

        // 针对无法区分非阻塞式IO错误，我们需要对错误码进行区分
        if (errno == EAGAIN || errno == EWOULDBLOCK) // RWOULDBLOCK 本质是 EAGAIN
        {
            std::cout << " IO资源未就绪, try again" << std::endl;
            continue; 
        }else if (errno == EINTR) // read时被signal打断，返回时无法再调用read
        {
            continue;
        }else
        {
            break;
        }
    }

    return 0;
}




